home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr49
/
121_01.zip
/
LOCAL.C
< prev
next >
Wrap
Text File
|
1993-06-01
|
12KB
|
524 lines
/*
HEADER: CUG 121.??;
TITLE: local - misc functions used on this disk;
VERSION: 1.0;
DATE: 12/01/85;
DESCRIPTION: "This file contains functions used by call.c, if.c, tel.c
and tl370.c. The following functions are included:
abort(), barf(), sign(), stacktop(), strncat(), strncmp(),
strncpy(), strlower(), strupper(), strindex(), index(),
findline(), getdph(), extract(), mputs(), mputc(), moready(),
mgetc(), miready(), hayesput(), hayesget(), globarg(),
posarg()";
KEYWORDS: functions;
SYSTEM: CP/M;
FILENAME: LOCAL.C;
WARNINGS: "This file contains some functions that are not used by
anything on this disk, but may be of general interest or use.";
AUTHORS: Mike W. Meyer, Steve Kenton;
COMPILERS: BDS-C 1.50;
*/
/*
* local.c - the local library of C functions for BDS C.
* copyright (c) 1981, Mike Meyer
* parts copyright (c) 1982, Steve Kenton
* modified stylewise to fit my conventions - mwm
*
* modified by rfb (Dec '85) -
* changed modem i/o to use v1.50 #defines, added mgetc()
* changed stacktop() to use topofmem()
* modified style & made it consistent throughout (apologies to
* anyone offended)
* added #include for v1.50 hardware values
*/
#include <bdscio.h>
#include <hardware.h>
#include "local.h"
/*
* barf - exit with a non-zero value, possible printing a message
*/
barf(chuck)
char *chuck;
{
abort(chuck);
}
/*
* abort - the real body of barf, used by the squeamish.
*/
abort(charles)
char *charles;
{
if (charles)
puts(charles);
exit(1);
}
/*
* sign - return 0, 1, -1 depending on the sign of x
*/
int sign(x)
{
return (x > 0) - (x < 0);
}
/*
* stacktop - just returns address of the top of the stack.
* uses v1.50 function topofmem()
*/
char *stacktop()
{
return topofmem();
}
/*
* strncpy - copy a substring up to N characters long
*/
strncpy(str1, str2, n)
char *str1, *str2;
unsigned n;
{
while (n-- && *str2)
*str1++ = *str2++;
*str1 = NULL;
}
/*
* strncat - cat a substring of up to N characters
*/
strncat(str1, str2, n)
char *str1, *str2;
unsigned n;
{
while (*str1++)
;
strncpy(str1 - 1, str2, n);
}
/*
* strncmp - compare a substring up to N characters long
*/
int strncmp(str1, str2, n)
char *str1, *str2;
unsigned n;
{
int i;
while (n--)
if (!*str1 && !*str2)
break;
else if (i = *str2++ - *str1++)
return(i);
return(0);
}
/*
* strlower - map a string to lower case
*/
char *strlower(string)
char *string;
{
char *x;
x = string;
do
*x = tolower(*x);
while (*++x);
return string;
}
/*
* strupper - map a string to upper case
*/
char *strupper(string)
char *string;
{
char *x;
x = string;
do
*x = toupper(*x);
while (*++x);
return string;
}
/*
* strindex - return the index of substr in str or error
*/
unsigned strindex(str, substr)
char *str, *substr;
{
int i, len, limit;
char save, *savloc; /* not needed if using strncmp */
len = strlen(substr);
limit = strlen(str) - len + 1;
for (i = 0; i < limit; i++) {
savloc = str + len;
save = *savloc; /* so save the current value */
*savloc = '\0'; /* and then terminate the substring */
if (strcmp(str, substr) == 0) {
*savloc = save; /* restore the saved character */
return(i); /* and return the index */
}
*savloc = save; /* restore the saved character */
str++; /* otherwise, increment the start address and repeat */
}
return(ERROR); /* not found, so return ERROR */
}
/*
* index - return the index of the first occurrence of C
* in str or error if it is not found
*/
unsigned index(str, c)
char *str, c;
{
int i;
for (i = 0; *str; i++)
if (*str++ == c)
return(i); /* found it */
return(ERROR); /* did not find it */
}
/*
* findline - this routine takes a BDS C file open for formatted I/O,
* a buffer buf, and a string. It returns, in buf, the first line
* in the file that matches the string, up to either a tab, a space,
* or a semicolon in the line from the file.
*/
int findline(file, line, pat)
char *file, *line, *pat;
{
char *lp, *pp;
while (fgets(line, file))
for (lp = line, pp = pat; ; pp++, lp++)
if (!*pp && index("\t :", *lp) != ERROR)
return TRUE;
else if (*pp != *lp || !*pp)
break;
return FALSE;
}
/*
* getdph - return the address of a disk parameter header
* or error if the drive is out of the range 0-15
* To guarentee the drive is configured, it is selected first
* This is performed by bios call 9, but the Bios() function
* can not be used, because it returns in <A> not <HL>
* After the header is located, the default drive is reselected
*/
dph *getdph(drive)
int drive;
{
unsigned *warmstart, seldsk, result;
char current;
current = bdos(GETCURRENT, 0); /* save the current drive */
warmstart = 1;
seldsk = *warmstart + 24; /* address of SELDSK routine */
if ((result = call(seldsk, 0, 0, drive, 0)) == 0)
return(ERROR); /* invalid drive */
bios(SELDSK,current); /* restore the original disk */
return(result);
}
/*
* extract - build a name string from an dir/fcb entry
* and place it in name. Return the user/drive number
*/
char extract(entry, name)
dir *entry;
char *name;
{
int i,n;
n = 0;
for (i = 0; (i < 8) && ((name[n] = entry -> dir_name[i]) != ' '); i++)
n++;
name[n++] = '.';
for (i = 0; (i < 3) && ((name[n] = entry -> dir_type[i]) != ' '); i++)
n++;
name[n] = '\0';
return(entry -> dir_user);
}
/*
* mputs - output the given string on the modem port
*/
mputs(string)
char *string;
{
while (*string)
mputc(*string++);
}
/*
* mputc - output the given character on the modem port
*/
mputc(byte)
char byte;
{
while (!moready())
;
MOD_TDATA(byte);
}
/*
* moready - is the modem ready to have a character go to it?
*/
int moready()
{
return MOD_TBE;
}
/*
* mgetc - input a character from the modem port
*/
char mgetc()
{
while (!miready())
;
return MOD_RDATA;
}
/*
* miready - is the modem ready to give me a character?
*/
int miready()
{
return MOD_RDA;
}
/*
* hayesput - output a command string to the hayes, and check the result
*/
char hayesput(string)
char *string;
{
mputs(string);
return hayesget();
}
/*
* hayesget - get a result byte from the hayes smartmodem
*/
char hayesget()
{
while (!miready())
;
return mgetc();
}
/*
* PARSE - last modified [18 FEB 82]
* General argument parsing routines for ARGC, and ARGV
* Globarg and Posarg are available to the user. All other
* routines are for internal use. There are no externals.
*/
/*
* GLOBARG - parse and assign global flags to variables
* return FALSE if there were errors in any of the arguments.
* Fmt is a format string similar to the one used by printf
* except a mandatory prefix and optional suffix can be specified.
* The types supported are boolean, char, string, and number.
* A default is required for each flag, and follows it in
* the format string delimited by a colon. The following is
* an example for two flag, one boolean, and one numeric
*
* ..."s|ymbols%b:false c|opies%n:1",&symbol,&copies...
*/
int globarg(argc,argv,formats,args)
int argc;
char *argv[],*formats[],args;
{
int i,flag,**results;
results = &args;
argv[0] = 1; /* argv[0] must be MANUALLY parsed beforehand */
if (_verify(formats,results) == ERROR)
return(FALSE);
while ((i = argv[0]) < argc) {
if ((flag = _parse(argc,argv,formats,results,TRUE)) == ERROR)
return(FALSE);
else if (!flag)
_incr(argc,argv);
}
argv[0] = 0; /* signal first time to POSARG */
return(TRUE);
}
/*
* POSARG - parse and assign positional flags to variables
* return a pointer to the next positional paramters, EOF,
* or FALSE if there is an error parsing one of the arguments.
* The formats and arguments are identical to those for GLOBARG
*/
int posarg(argc,argv,formats,args)
int argc;
char *argv[],*formats[],args;
{
int i,flag,**results;
results = &args;
if ((!argv[0]) && (_verify(formats,results) == ERROR))
return(FALSE);
_incr(argc,argv); /* dump the last positional parameter */
while ((i = argv[0]) < argc) {
if ((flag = _parse(argc,argv,formats,results,FALSE)) == ERROR)
return(FALSE);
else if (!flag)
return(argv[i]);
}
return(EOF);
}
/*
* _PARSE - an internal routine to parse the flags
* argv[0] contains the current argument index to use.
* Return TRUE or FALSE depending on the _match, and
* ERROR if a required argument is missing or invalid.
* Oneonly is a flag indicating arguments must be unique
*/
int _parse(argc,argv,formats,results,oneonly)
int argc,*results[],oneonly;
char *argv[],*formats[];
{
int i,pos;
char *str;
if (!formats) /* no format array specified */
return(FALSE);
pos = argv[0];
if (*argv[pos] == '-')
for (i=0; str=formats[i]; i++) {
if (_match(str,argv[pos])) {
argv[pos++] = NULL; /* remove it from processing */
_incr(argc,argv);
switch (str[index(str,'%')+1]) {
case 'B': /* convert to boolean */
*results[i] = !(*results[i]);
break;
case 'C': /* convert to character */
poke(results[i],*argv[pos]);
argv[pos++] = NULL;
_incr(argc,argv);
break;
case 'N': /* convert to numeric */
*results[i] = atoi(argv[pos]);
argv[pos++] = NULL;
_incr(argc,argv);
break;
case 'S': /* convert to string */
strcpy(results[i],argv[pos]);
argv[pos++] = NULL;
_incr(argc,argv);
break;
default:
puts("This cannot happen #1\n");
return(ERROR);
}
if (oneonly) /* check for duplicated arguments */
while (pos < argc) {
if (_match(str,argv[pos])) {
printf("Unique argument '%s' duplicated\n",argv[pos]);
return(ERROR);
}
pos++;
}
return(TRUE);
}
}
return(FALSE);
}
/*
* _VERIFY - verify the format strings and assign defaults
* return OK, or ERROR depending whether errors were detected
*/
int _verify(formats,results)
char *formats[];
int *results[];
{
int i,valid,percent,bar,colon;
char *str;
if (!formats) /* no format array specified */
return(OK);
valid = OK;
for (i=0; str=formats[i]; i++) {
strupper(str); /* fold to caps for the command line */
percent = index(str,'%');
bar = index(str,'|');
colon = index(str,':');
if ((bar == 0) || (percent <= 0) || (colon <= 0)
|| (colon < percent) || (index("BCNS",str[percent+1]) == ERROR)) {
printf("Argument parser format error on '%s'\n",str);
valid = ERROR;
}
switch(str[percent+1]) {
case 'B': /* Boolean flag */
if (str[colon+1] == 'T')
*results[i] = TRUE;
else *results[i] = FALSE;
break;
case 'C': /* Character flag */
poke(results[i],str[colon+1]);
break;
case 'S': /* String flag */
strcpy(results[i],&str[colon+1]);
break;
case 'N': /* Numeric flag */
*results[i] = atoi(&str[colon+1]);
break;
default:
puts("This cannot happen #2\n");
valid = ERROR;
}
}
return(valid);
}
/*
* _MATCH - pattern _match the argument flag prefix/suffix
* and return TRUE or FALSE depending on the result.
* If more than the required prefix is specified, then the
* WHOLE string must _match both the prefix and suffix.
*/
int _match(pattern,string)
char *pattern,*string;
{
int i;
string++;
if ((i = index(pattern,'|')) == ERROR)
i = index(pattern,'%');
if (!strncmp(string,pattern,i))
return(TRUE);
return(FALSE);
}
/*
* _INCR - increment the argument index in argv[0]
* skipping any previously parsed entries (set to NULL)
*/
_incr(argc,argv)
int argc;
char *argv[];
{
int i;
for (i=argv[0]+1; i<argc; i++) {
if (argv[i]) {
argv[0] = i;
return;
}
}
argv[0] = argc;
}